package production

import (
	"encoding/json"
	"fmt"
	"github.com/hyperledger/fabric/core/chaincode/shim"
	sc "github.com/hyperledger/fabric/protos/peer"
)

type ProductUnit struct {
	BatchInfo UnitInfo `json:"batch_info"`
	UnitNos   []string `json:"unit_nos"`
}

type UnitInfo struct {
	ProductTime   string `json:"product_time"`
	ItemNo        string `json:"item_no"`
	EnterBatch    string `json:"enter_batch"`
	Producer      string `json:"producer"`
	Environment   string `json:"environment"`
	MaterialBatch string `json:"material_batch"`
	EnterTime     string `json:"enter_time"`
	NumOfSonPacks string `json:"num_of_son_packs"`
	PackLevel     string `json:"pack_level"`
}

type RepackageInfo struct {
	ItemInfo    UnitInfo  `json:"item_info"`
	QueriedInfo QueryInfo `json:"queried_info"`
}

type QRInfo struct {
	ItemInfo     UnitInfo    `json:"item_info"`
	QueryHistory []QueryInfo `json:"query_history"`
}

type QueryInfo struct {
	Address        string `json:"address"`
	QueryTime      string `json:"query_time"`
	BeQueriedTimes int    `json:"be_queried_times"`
}

func (p ProductUnit) SaveProductUnitInfo(APIstub shim.ChaincodeStubInterface, batchKey string) sc.Response {
	finalBatchKey, err := APIstub.CreateCompositeKey("BatchForProduct", []string{string([]byte(batchKey)[0:35]), batchKey})
	if err != nil {
		return shim.Error("系统错误。")
	}
	value, err := json.Marshal(p)
	if err != nil {
		return shim.Error("系统错误。")
	}
	err = APIstub.PutState(finalBatchKey, value)
	if err != nil {
		return shim.Error("系统错误。")
	}
	return shim.Success(nil)
}

func (p *ProductUnit) QueryProductUnitInfo(APIstub shim.ChaincodeStubInterface, itemNo string) error {
	valueIterator, err := APIstub.GetStateByPartialCompositeKey("BatchForProduct", []string{string([]byte(itemNo)[0:35])})
	if err != nil {
		return err
	} else if valueIterator == nil {
		return fmt.Errorf("找不到您查询的商品。")
	}

	flag := false
	for valueIterator.HasNext() {
		value, err := valueIterator.Next()
		if err != nil {
			return err
		}

		var pt ProductUnit

		err = json.Unmarshal(value.Value, &pt)
		if err != nil {
			return err
		}

		if pt.checkItemsNo(itemNo) {
			flag = true
			*p = pt
			break
		}
	}
	if !flag {
		return fmt.Errorf("找不到您查询的商品。")
	}
	return nil
}

func (p ProductUnit) checkItemsNo(itemNo string) bool {
	flag := false
	for _, i := range p.UnitNos {
		if i == itemNo {
			flag = true
		}
	}
	return flag
}

func (p ProductUnit) Repackage(APIstub shim.ChaincodeStubInterface, address string, queryTime string, itemNo string) error {

	repackageInfo := RepackageInfo{
		p.BatchInfo,
		QueryInfo{
			address,
			queryTime,
			1,
		},
	}

	value, err := json.Marshal(repackageInfo)
	if err != nil {
		return err
	}
	err = APIstub.PutState(itemNo, value)
	if err != nil {
		return err
	}

	return nil
}

func (q *QRInfo) QueryByQR(APIstub shim.ChaincodeStubInterface, qR string, value []byte) error {
	//value, err := APIstub.GetState(qR)
	//if err != nil {
	//	return err
	//} else if value == nil {
	//	return fmt.Errorf("找不到您查询的商品。")
	//}

	var repackageInfo RepackageInfo
	err := json.Unmarshal(value, &repackageInfo)
	q.ItemInfo = repackageInfo.ItemInfo

	iterator, err := APIstub.GetHistoryForKey(qR)
	if err != nil {
		return err
	}
	defer iterator.Close()

	var history []QueryInfo
	for iterator.HasNext() {
		response, err := iterator.Next()
		if err != nil {
			return err
		}
		var q QueryInfo
		err = json.Unmarshal(response.Value, &q)
		if err != nil {
			return err
		}
		history = append(history, q)
	}
	q.QueryHistory = history
	return nil
}

func (r *RepackageInfo) UpdateQueryInfo(APIstub shim.ChaincodeStubInterface, address string, queryTime string, qR string) error {
	value, err := APIstub.GetState(qR)
	if err != nil {
		return err
	} else if value == nil {
		return fmt.Errorf("找不到您查询的商品。")
	}

	err = json.Unmarshal(value, r)
	r.QueriedInfo.Address = address
	r.QueriedInfo.QueryTime = queryTime
	r.QueriedInfo.BeQueriedTimes += 1

	value, err = json.Marshal(r)
	if err != nil {
		return err
	}
	err = APIstub.PutState(qR, value)
	if err != nil {
		return err
	}

	return nil
}
